/**
 *
 */

(function(){
	var Vector2 = function Vector2(){
		if( arguments.length === 2  &&
				typeof arguments[0] === 'number' &&
				typeof arguments[1] === 'number' ){
			this.x = arguments[0];
			this.y = arguments[1];
		}else if( arguments.length === 0 ){
			this.x = 0;
			this.y = 0;
		}else{
			throw 'Arguments must be 2 numbers or nothing at all';
		}
	};
	var proto = Vector2.prototype;
	
	Vector2.type = 'Vector2';
	proto.type = Vector2.type;
	
	proto.set = function set( x, y ){
		if( arguments.length === 2 &&
				typeof arguments[0] === 'number' &&
				typeof arguments[1] === 'number' ){
			this.x = arguments[0];
			this.y = arguments[1];
		}else if( arguments.length === 1 && arguments[0].type === Vector2.type ){
			this.x = arguments[0].x;
			this.y = arguments[0].y;
		}else{
			throw 'Argument must be 2 numbers or 1 "Vector2"';
		}
	};
	
	proto.neg = function neg(){
		return new Vector2( -this.x, -this.y );
	};
	
	proto.add = function add( x ){
		var output = new Vector2( this.x, this.y );
		if( typeof x === 'number' ){
			output.x += x;
			output.y += x;
		}else if( x instanceof Box2d.Math.Vector2 ){
			output.x += x.x;
			output.y += x.y;
		}else{
			throw 'Argument must be of type "Vector2" or "number"';
		}
		return output;
	};
	
	proto.sub = function sub( x ){
		var output = new Vector2( this.x, this.y );
		if( typeof x === 'number' ){
			output.x -= x;
			output.y -= x;
		}else if( x.type && x.type === Vector2.type ){
			output.x -= x.x;
			output.y -= x.y;
		}else{
			throw 'Argument must be of type "Vector2" or "number"';
		}
		return output;
	};
	
	proto.mul = function mul( x ){
		var output = new Vector2( this.x, this.y );
		if( typeof x === 'number' ){
			output.x *= x;
			output.y *= x;
		}else if( x.type && x.type === Vector2.type ){
			output.x *= x.x;
			output.y *= x.y;
		}else{
			throw 'Argument must be of type "Vector2" or "number"';
		}
		return output;
	};
	
	proto.dot = function dot( x ){
		if( !x || !x.type || x.type !== Vector2.type ){
			throw 'Arguments must be of type "Vector2"';
		}
		return this.x * x.x + this.y * x.y;
	};
	
	proto.square = function square(){
		return new Vector2( this.x * this.x, this.y * this.y );
	};
	
	proto.length = function length(){
		return Math.sqrt( this.x * this.x + this.y * this.y );
	};
	
	proto.abs = function abs(){
		return new Vector2( Math.abs( this.x ), Math.abs( this.y ) );
	};
	
	Vector2.dot = function dot( a, b ){
		if( a.type !== Vector2.type || b.type !== Vector2.type ){
			throw 'Arguments must be of type "Vector2"';
		}
		return a.x * b.x + a.y * b.y;
	};
	
	Vector2.crossVV = function crossVV( a, b ){
		if( a.type !== Vector2.type || b.type !== Vector2.type ){
			throw 'Arguments must be of type "Vector2"';
		}
		return a.x * b.y - a.y * b.x;
	};
	
	Vector2.crossVN = function crossVN( a, s ){
		if( a.type !== Vector2.type || typeof s !== 'number' ){
			throw 'Arguments must be of type "Vector2" and "number"';
		}
		return new Vector2( s * a.y, -s * a.x );
	};
	
	Vector2.crossNV = function crossNV( s, a ){
		if( typeof s !== 'number' || a.type !== Vector2.type ){
			throw 'Arguments must be of type "number" and "Vector2"';
		}
		return new Vector2( -s * a.y, s * a.x );
	};
	
	Vector2.abs = function abs( a ){
		if( a.type !== Vector2.type ){
			throw 'Argument must be of type "Vector2"';
		}
		return new Vector2( Math.abs( a.x ), Math.abs( a.y ) );
	};
	
	Box2d.Math.Vector2 = Vector2;
})();